﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using SwAddinHelpers.Contracts;
using SwAddinHelpers.Attributes;

using System.Reflection;
using System.ComponentModel.Composition;
using System.ComponentModel.Design;
using System.ComponentModel.Composition.Hosting;

namespace SwAddinHelpers.AddinManager
{
    public enum enumDebugMsgType
    {
        UserExecution,
        UserExecution1,
        UserExecution2,
        UserExecution3,
        SystemExecution,
        CallbackExecution,
        Callback,
        Subscription,
        Unsubscription,
        Addin,
        Exception,
        Other
    }

    public partial class DebugManager : Form
    {
        private ISwAddinBaseDebug _ownerDebug = null;
        private ISwAddinBase _ownerAddin = null;

        private int eventsPosted = 0;

        public DebugManager(ISwAddinBase ownerAddin)
        {
            InitializeComponent();
            lvEvents.MouseDoubleClick += new MouseEventHandler(lvEvents_MouseDoubleClick);
            tvControlExposure.NodeMouseDoubleClick += new TreeNodeMouseClickEventHandler(tvControlExposure_NodeMouseDoubleClick);
            this.FormClosing += new FormClosingEventHandler(DebugManager_FormClosing);
            _ownerDebug = ownerAddin.Debug;
            _ownerAddin = ownerAddin;
        }

        void DebugManager_FormClosing(object sender, FormClosingEventArgs e)
        {
            _ownerDebug.ContinueLoadingAddin();
        }

        void tvControlExposure_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            try
            {
                if (e.Node.Tag == "FLASH")
                {
                   /*
                    ManagedWinapi.Windows.SystemWindow window = new ManagedWinapi.Windows.SystemWindow(_ownerAddin.RetrieveUIHostByProgId(e.Node.Text).externalControl);
                    try
                    {

                        SwAddinHelpers.ComHelpers.pinvoke.FLASHWINFO fInfo = new SwAddinHelpers.ComHelpers.pinvoke.FLASHWINFO();

                        fInfo.cbSize = Convert.ToUInt32(System.Runtime.InteropServices.Marshal.SizeOf(fInfo));
                        fInfo.hwnd = window.HWnd;
                        fInfo.dwFlags = SwAddinHelpers.ComHelpers.pinvoke.FLASHW_ALL | SwAddinHelpers.ComHelpers.pinvoke.FLASHW_TIMERNOFG;
                        fInfo.uCount = UInt32.MaxValue;
                        fInfo.dwTimeout = 0;

                        SwAddinHelpers.ComHelpers.pinvoke.FlashWindowEx(ref fInfo);
                    }
                    catch { }
                    window = null;
                    */
                }
            }
            catch { }
        }

        void lvEvents_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            try
            {
                MessageBox.Show(lvEvents.SelectedItems[0].Tag.ToString());
            }
            catch { }
        }

        public void PostEvent(enumDebugMsgType msgType = enumDebugMsgType.UserExecution, string msg = "N/A", params string[] parameters)
        {
            eventsPosted++;

            if (!_ownerDebug.IsDebuggerAttached) return;

            string Source = "See Stack Trace";
            try
            {
               Source =   new System.Diagnostics.StackFrame(1).GetMethod().ReflectedType.Name + "." + new System.Diagnostics.StackFrame(1).GetMethod().Name;
            }
            catch { }
            string paramString = "N/A";
            if (parameters != null)
            {
                paramString = String.Join("\r\n\t", parameters);
            }
            string newline = "\r\n\r\n";

            ListViewItem lvitem = new ListViewItem(eventsPosted.ToString());
            lvitem.Tag = "Event#: " + eventsPosted.ToString() + newline +
                "Source: " + Source + newline +
                "MsgType: "  + msgType.ToString() + newline +
                "MsgText: " + msg + newline +
                "Info:\r\n\t" + paramString + newline +
                "Stack:" + new System.Diagnostics.StackTrace().ToString();
            lvitem.SubItems.Add(Source);
            lvitem.SubItems.Add(msgType.ToString());
            lvitem.SubItems.Add(msg);
            lvEvents.Items.Insert(0, lvitem);

            if (chkManualNotify.Checked) MessageBox.Show(lvitem.Tag.ToString());
        }

        private void DebugManager_Load(object sender, EventArgs e)
        {
            GetProcessInfo();

            chkIsXP.Checked = _ownerAddin.IsWindowsXP;
        }

        private void GetProcessInfo()
        {
            System.Diagnostics.Process p = System.Diagnostics.Process.GetCurrentProcess();
            pgProcess.SelectedObject = p;
        }

        

        private void chkLoadTP_CheckedChanged(object sender, EventArgs e)
        {
            _ownerDebug.loadTP = chkLoadTP.Checked;
        }

        private void chkLoadFV_CheckedChanged(object sender, EventArgs e)
        {
            _ownerDebug.loadFV = chkLoadFV.Checked;
        }

        private void chkLoadMV_CheckedChanged(object sender, EventArgs e)
        {
            _ownerDebug.loadMV = chkLoadMV.Checked;
        }

        private void chkLoadPMP_CheckedChanged(object sender, EventArgs e)
        {
            _ownerDebug.loadPMP = chkLoadPMP.Checked;
        }

        private void chkLoadMenu_CheckedChanged(object sender, EventArgs e)
        {
            _ownerDebug.loadMenu = chkLoadMenu.Checked;
        }

        private void chkLoadCommand_CheckedChanged(object sender, EventArgs e)
        {
            _ownerDebug.loadCommand = chkLoadCommand.Checked;
        }

        private void chkBuildProxy_CheckedChanged(object sender, EventArgs e)
        {
            _ownerDebug.buildProxy1 = chkBuildProxy.Checked;
        }

        private void btnOk_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnContinue1_Click(object sender, EventArgs e)
        {
            _ownerDebug.ContinueLoadingAddin();
            groupBox1.Enabled = false;
        }

        private void btnRefresh1_Click(object sender, EventArgs e)
        {
            GetProcessInfo();
        }

        private void lnkClearEvents_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            lvEvents.Items.Clear();
        }

        private void chkOwned_CheckedChanged(object sender, EventArgs e)
        {
            _ownerDebug.Is0wned = chkOwned.Checked;
        }

        private void chkLoadForms_CheckedChanged(object sender, EventArgs e)
        {
            _ownerDebug.loadForms = chkLoadForms.Checked;
        }

        private void btnRefreshControlExposure_Click(object sender, EventArgs e)
        {
            tvControlExposure.Nodes.Clear();

            TreeNode tnRoot = new TreeNode("Component Surface Explorer");
            tnRoot.Expand();

            foreach (SwAddinHelpers.Base.UserControlHostBase hb in _ownerAddin.HostCollection)
            {
                TreeNode tnParent = new TreeNode(hb.HostedControlTypeProgId);
                tnParent.Tag = "FLASH";
                TreeNode tnCategory = new TreeNode("Invokable Methods");
                tnParent.Nodes.Add(tnCategory);

                List<MethodInfo> ims = hb.GetInvokableMethods();

                foreach (MethodInfo mi in ims)
                {                       
                    TreeNode tnChild = new TreeNode(mi.ToString());
                    tnChild.Tag = mi;
                    tnCategory.Nodes.Add(tnChild);
                }

                tnCategory = new TreeNode("Sinkable Methods");
                tnParent.Nodes.Add(tnCategory);

                List<SinkMethodAttribute> sma = hb.GetSinkableMethodAttributes(hb.externalControl);

                foreach (SinkMethodAttribute sm in sma)
                {
                    TreeNode tnChild = new TreeNode(sm.methodInfo.ToString() + " <-- " + sm.SourceEvent.ToString());
                    tnChild.Tag = sm;
                    tnCategory.Nodes.Add(tnChild);
                }

                tnCategory = new TreeNode("Active Sinks");
                tnParent.Nodes.Add(tnCategory);

                foreach (KeyValuePair<string, SwAddinHelpers.Base.SubscribedEventInfo> se in hb.SubscribedEvents)
                {
                    TreeNode tnChild = new TreeNode(se.Value.eventSink.ToString() + " @" + se.Value.eventSource.ToString());
                    tnCategory.Nodes.Add(tnChild);
                }


                tnRoot.Nodes.Add(tnParent);
            }

            // get delegates
            Dictionary<string, Delegate> delegates =  _ownerAddin.MainAppEventSink.GetDelegates();
            TreeNode tnDelegateParent = new TreeNode("Delegate Invocation Lists");
            tnDelegateParent.Expand();

            foreach (KeyValuePair<string, Delegate> d in delegates)
            {
                TreeNode tnDelChild = new TreeNode(d.Key.ToString());

                if (d.Value != null)
                {
                    foreach (Delegate d1 in d.Value.GetInvocationList())
                    {
                        TreeNode tnDelChild2 = new TreeNode(d1.Target.ToString() + "." + d1.Method.ToString());
                        tnDelChild.Nodes.Add(tnDelChild2);
                    }
                }
                else
                {
                    TreeNode tnDelChild2 = new TreeNode("no subscribers");
                    tnDelChild.Nodes.Add(tnDelChild2);
                }

                tnDelegateParent.Nodes.Add(tnDelChild);
            }

            tvControlExposure.Nodes.Add(tnRoot);
            tvControlExposure.Nodes.Add(tnDelegateParent);
        }


        

      

        
    }
}
